﻿using Cube.Data;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CubeForm.AI
{
    class PLL : IPattenMatch
    {
        Cube.Data.Cube cube;
        PattenManager patten;

        public event PattenMatchedDelegate PattenMatched;

        public PLL(Cube.Data.Cube cube)
        {
            this.cube = cube;
            patten = new PattenManager(cube);
        }

        public void Invoke()
        {
            if (CheckSkip())
            {
                Debug.WriteLine("Skipped PLL");
            }
            else
            {
                if (!SetEyes())
                {
                    // 若第一次没有找到"眼"，做一次角位移公式后再寻找
                    DoPLLAnglePatten();
                    SetEyes();
                }
                DoPLLAnglePatten();

                if (!SetLine())
                {
                    // 若第一次没有找到三色一线，做一次棱位移公式后再寻找
                    DoPLLSidePatten();
                    SetLine();
                }
                while (cube[new PositionVector(0, 1, 1)].Y != cube[new PositionVector(1, 1, 1)].Y)
                {
                    DoPLLSidePatten();
                }
            }
            var front_color = cube[new PositionVector(0, 1, 0)].Y;
            while(cube[new PositionVector(0, 1, 1)].Y != front_color)
            {
                patten.U();
            }
            Debug.WriteLine("Whole Cube Done!");
            PattenMatched?.Invoke(patten.GetRecord());
        }

        private bool SetEyes()
        {
            for(var i = 0; i < 4; i++)
            {
                var front = cube.GetFace(Faces.Front);
                if (front[0, 0] == front[0, 2])
                {
                    Debug.WriteLine("Eyes Found.");
                    return true;
                }
                patten.U();
            }
            Debug.WriteLine("Eyes Not Found.");
            return false;
        }

        /// <summary>
        /// 检查是否能够跳P
        /// </summary>
        /// <returns></returns>
        private bool CheckSkip()
        {
            var front = cube.GetFace(Faces.Front);
            var right = cube.GetFace(Faces.Right);
            if(front[0, 0] == front[0, 1] && front[0, 0] == front[0, 2])
            {
                if (right[0, 0] == right[0, 1] && right[0, 0] == right[0, 2])
                {
                    return true;
                }
            }
            return false;
        }

        private bool SetLine()
        {
            for (var i = 0; i < 4; i++)
            {
                var behind = cube.GetFace(Faces.Behind);
                if (behind[0, 0] == behind[0, 1] && behind[0, 0] == behind[0, 2])
                {
                    Debug.WriteLine("Line Found.");
                    return true;
                }
                patten.U();
            }
            Debug.WriteLine("Line Not Found.");
            return false;
        }

        /// <summary>
        /// 做一次角位移公式
        /// </summary>
        private void DoPLLAnglePatten()
        {
            patten.R(); patten.B(); patten.R(); patten.F(); patten.F();
            patten._R(); patten._B(); patten.R(); patten.F(); patten.F();
            patten.R(); patten.R();
            Debug.WriteLine("Angle Patten Done.");
        }

        /// <summary>
        /// 做一次棱位移公式
        /// </summary>
        private void DoPLLSidePatten()
        {
            patten.R(); patten._U(); patten.R();
            patten.U(); patten.R(); patten.U(); patten.R();
            patten._U(); patten._R(); patten._U(); patten.R(); patten.R();
            Debug.WriteLine("Side Patten Done.");
        }
    }
}
